import java.util.ArrayList;


public class XmlElement {
	
	String name;
	
	ArrayList<XmlElement> elementList;
	ArrayList<XmlAttribute> attributeList;
	String textContent;
	
	boolean isRoot;
	String version;
	String encoding;
	
	int indent;
	
	public XmlElement(String name)
	{
		this.name = escapeXml(name);
		isRoot = false;
		
		elementList = new ArrayList<XmlElement>();
		attributeList = new ArrayList<XmlAttribute>();
	}
	
	public XmlElement(String name, String version, String encoding)
	{
		this.name = escapeXml(name);
		isRoot = true;
		this.version = version;
		this.encoding = encoding;
		
		elementList = new ArrayList<XmlElement>();
		attributeList = new ArrayList<XmlAttribute>();
		
		indent = 0;
	}
	
	public void addElement(XmlElement element)
	{
		element.setIndent(indent + 1);
		elementList.add(element);
	}
	
	public void setTextContent(String content)
	{
		textContent = escapeXml(content);
	}
	
	public void addAttribute(String name, String value)
	{
		attributeList.add(new XmlAttribute(escapeXml(name), escapeXml(value)));
	}
	
	/*
	public void addAttribute(XmlAttribute attribute)
	{
		attributeList.add(attribute);
	}
	*/
	
	private void setIndent(int indent)
	{
		this.indent = indent;
	}
	
	private StringBuffer toStringBuffer()
	{
		StringBuffer buf = new StringBuffer();
		
		String indentTabs = "";
		for (int i = 0; i < indent; i++)
		{
			indentTabs += "    ";
		}
		
		if (isRoot)
		{
			buf.append("<?xml version=\"" + version + "\" encoding=\"" + encoding + "\"?>\n");
		}
		
		buf.append("<" + name);
		
		for (int i = 0; i < attributeList.size(); i++)
		{
			buf.append( " " + attributeList.get(i));
		}
		
		buf.append(">");
		if (textContent != null)
			buf.append(textContent);
		
		if (elementList.size() != 0)
			buf.append("\n");
		
		for (int i = 0; i < elementList.size(); i++)
		{
			buf.append(indentTabs + "    " + elementList.get(i).toStringBuffer() + "\n");
		}
		
		if (elementList.size() == 0)
			buf.append("</" + name + ">");
		else
			buf.append(indentTabs + "</" + name + ">");
			
		
		return buf;
	}
	
	public String toString()
	{
		return toStringBuffer().toString();
	}
	
	/*
	 	&lt; 	< 	less than
		&gt; 	> 	greater than
		&amp; 	& 	ampersand 
		&apos; 	' 	apostrophe
		&quot; 	" 	quotation mark
	 */
	private String escapeXml(String str)
	{
		return str.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;")
			.replaceAll("'", "&apos;").replaceAll("\"", "&quot;");
	}
	
	public static void main(String[] args)
	{
		XmlElement root = new XmlElement("root", "1.0", "ISO-8859-1");
		XmlElement test1 = new XmlElement("test1");
		XmlElement test2 = new XmlElement("test2");
		XmlElement subtest11 = new XmlElement("subtest11");
		XmlElement subtest12 = new XmlElement("subtest12");
		XmlElement subtest13 = new XmlElement("subtest13");
		XmlElement subtest21 = new XmlElement("subtest21");
		XmlElement subtest22 = new XmlElement("subtest22");
		XmlElement subtest23 = new XmlElement("subtest23");
		subtest11.setTextContent("This is a test.");
		subtest12.setTextContent("And again!");
		subtest13.setTextContent("And again!");
		subtest13.addAttribute("hi", "there");
		subtest13.addAttribute("never", "again");
		subtest21.setTextContent("<>&'\"");
		test1.addAttribute("id", "314");
		test1.addAttribute("name", "Jonathan");
		test1.addElement(subtest11);
		test1.addElement(subtest12);
		test1.addElement(subtest13);
		test2.addElement(subtest21);
		test2.addElement(subtest22);
		test2.addElement(subtest23);
		test2.setTextContent("Hieu");
		root.addElement(test1);
		root.addElement(test2);
		System.out.println(root);
	}
}
